package com.upper.service.nginxserver;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import org.lucksyc.utilindependent.resultview.core.data.ViewData;
import org.lucksyc.utilindependent.resultview.seed.deal.ViewBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bean.Computer;
import com.bean.NginxService;
import com.bean.ServiceList;
import com.componentbean.UserNginxSet;
import com.lower.service.ipall.CommonIpAllInterface;
import com.lower.service.ipself.CommonIpSelfInterface;
import com.model.ServiceModel;
import com.model.ServiceQuery;
import com.util.Util;

@Service
public class NginxServerInterfaceImpl implements NginxServerInterface {
//	private static final Logger log = LoggerFactory.getLogger(NginxServerInterfaceImpl.class);
	
	@Autowired
	ViewBuilder viewBuilder;
	
	@Autowired
	UserNginxSet userset;
	
	@Autowired 
	CommonIpAllInterface commonIpAllInterface;
	
	@Autowired 
	CommonIpSelfInterface commonIpSelfInterface;
	
	@Override
	public ViewData getServiceList(boolean isBs) {
		if (isBs) {
			if (null == userset.getServiceList().getServiceBs()) {
				return viewBuilder.wrapPageToJson(null, 0);
			} else {
				int total = userset.getServiceList().getServiceBs().size();
				List<ServiceModel> list = new ArrayList<>(total);
				Iterator<Entry<Integer, NginxService>> iterator = userset.getServiceList().getServiceBs().entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<Integer, NginxService> entry = iterator.next();
					NginxService service = entry.getValue();
					
					ServiceModel model = new ServiceModel();
					model.setsName(service.getServerName());
					model.setSid(entry.getKey().toString());
					
					Computer c = userset.getComputerById(service.getListenId());
					if (null == c) continue;
					model.setsListenId(String.valueOf(c.getId()));
					model.setsListenIp(String.valueOf(c.getIp()));
					model.setsListenPort(String.valueOf(service.getListenPort()));
					
					c = userset.getComputerById(service.getFontEndId());
					if (null == c) continue;
					model.setFontEndId(String.valueOf(c.getId()));
					model.setFontEndIp(String.valueOf(c.getIp()));
					model.setFontEndPort(String.valueOf(service.getFontEndPort()));
					
					c = userset.getComputerById(service.getBackEndId());
					if (null == c) continue;
					model.setBackEndId(String.valueOf(c.getId()));
					model.setBackEndIp(c.getIp());
					model.setBackEndPort(String.valueOf(service.getBackEndPort()));
					
					model.setAllowXlsx(String.valueOf(entry.getValue().getSupportXLSX()));
					list.add(model);
				}
				return viewBuilder.wrapPage(list, total);
			}
		} else {
			if (null == userset.getServiceList().getServiceCs()) {
				return viewBuilder.wrapPageToJson(null, 0);
			} else {
				int total = userset.getServiceList().getServiceBs().size();
				List<ServiceModel> list = new ArrayList<>(total);
				Iterator<Entry<Integer, NginxService>> iterator = userset.getServiceList().getServiceCs().entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<Integer, NginxService> entry = iterator.next();
					NginxService service = entry.getValue();
					
					ServiceModel model = new ServiceModel();
					model.setsName(service.getServerName());
					model.setSid(entry.getKey().toString());
					
					Computer c = userset.getComputerById(service.getListenId());
					model.setsListenId(String.valueOf(c.getId()));
					model.setsListenIp(String.valueOf(c.getIp()));
					model.setsListenPort(String.valueOf(service.getListenPort()));
					
					c = userset.getComputerById(service.getFontEndId());
					model.setFontEndId(String.valueOf(c.getId()));
					model.setFontEndIp(String.valueOf(c.getIp()));
					model.setFontEndPort(String.valueOf(service.getFontEndPort()));
					
					c = userset.getComputerById(service.getBackEndId());
					model.setBackEndId(String.valueOf(c.getId()));
					model.setBackEndIp(c.getIp());
					model.setBackEndPort(String.valueOf(service.getBackEndPort()));
					
					model.setAllowXlsx(String.valueOf(entry.getValue().getSupportXLSX()));
					list.add(model);
				}
				return viewBuilder.wrapPageToJson(list, total);
			}
		}
	}

	@Override
	public ViewData delService(boolean isBs,String id) {
		if (Util.isPositiveInteger(id)) {
			int sid = Integer.parseInt(id);
			NginxService nginxService = isBs?userset.getServiceList().getServiceBs().get(sid)
					:userset.getServiceList().getServiceCs().get(sid);
			if (null!= nginxService) {
				// 解除端口
				userset.getComputerSelf().getPortSet().remove(nginxService.getListenPort());
				if (nginxService.getFontEndId()<=0) {
					userset.getComputerSelf().getPortSet().remove(nginxService.getFontEndPort());
				}
				if (nginxService.getBackEndId()<=0) {
					userset.getComputerSelf().getPortSet().remove(nginxService.getBackEndPort());
				}
				// 移除IP的ID与服务ID的关联后要判断map里key是否还有值
				Set<Integer> assertexistid = new HashSet<>(3); 
				if (userset.getServiceList().getMap().get(nginxService.getListenId()).remove(nginxService.getId())) {
					assertexistid.add(nginxService.getListenId());
				}
				if (userset.getServiceList().getMap().get(nginxService.getFontEndId()).remove(nginxService.getId())) {
					assertexistid.add(nginxService.getFontEndId());
				}
				if (userset.getServiceList().getMap().get(nginxService.getBackEndId()).remove(nginxService.getId())) {
					assertexistid.add(nginxService.getBackEndId());
				}
				for (Integer e : assertexistid) {
					if (userset.getServiceList().getMap().get(e).isEmpty()) {
						userset.getServiceList().getMap().remove(e);
					}
				}
				if (isBs) {
					userset.getServiceList().getServiceBs().remove(sid);
				} else {
					userset.getServiceList().getServiceCs().remove(sid);
				}
				return viewBuilder.wrap(true);
			} else {
				return viewBuilder.wrapError("数据不存在",30420);
			}
		} else {
			return viewBuilder.wrapError("参数不合法",30450);
		}
	}

	@Override
	public ViewData saveService(ServiceQuery query) {
		if (Util.isPositiveInteger(query.getSid())) {
			return editService(query);
		} else {
			return addService(query);
		}
	}

	private ViewData editService(ServiceQuery query) {
		Integer listenid = null;
		if (Util.isNonPositiveInteger(query.getsListenId())) {
			listenid = Integer.parseInt(query.getsListenId());
			if (listenid < 0 && !userset.getComputerSelf().getOther().containsKey(listenid)) {
				return viewBuilder.wrapError("监听IP对应的信息不存在", 20501);
			}
		}
		NginxService newBean = new NginxService();
		newBean.setListenId(listenid);
		newBean.setServerName(query.getsName());
		newBean.setListenId(Util.isInteger(query.getFontEndId())?Integer.parseInt(query.getsListenId()):null);
		newBean.setListenPort(Util.isPort(query.getsListenPort())?Integer.parseInt(query.getsListenPort()):null);
		newBean.setFontEndId(Util.isInteger(query.getFontEndId())?Integer.parseInt(query.getFontEndId()):null);
		newBean.setFontEndPort(Util.isPort(query.getFontEndPort())?Integer.parseInt(query.getFontEndPort()):null);
		newBean.setBackEndId(Util.isInteger(query.getBackEndId())?Integer.parseInt(query.getBackEndId()):null);
		newBean.setBackEndPort(Util.isPort(query.getBackEndPort())?Integer.parseInt(query.getBackEndPort()):null);
		newBean.setSupportXLSX(null == query.getsSendXlsx()?null:"true".equals(query.getsSendXlsx()));
		
		boolean isBs = query.isTypeBs();
		int sid = Integer.parseInt(query.getSid());
		
		NginxService oldBean = (isBs?userset.getServiceList().getServiceBs().get(sid):userset.getServiceList().getServiceCs().get(sid));
		if (null == oldBean) {
			return viewBuilder.wrapError("没有可供修改的数据", 20503);
		}
		if (merge(newBean, oldBean)) {
			return viewBuilder.wrapError("没有要修改的数据内容", 20505);
		}
		/**
		 * 	端口号检查
		 */
		Set<Integer> useport = userset.getComputerSelf().getPortSet();
		useport.remove(oldBean.getListenPort());
		if (oldBean.getFontEndId()<=0) {
			useport.remove(oldBean.getFontEndPort());
		}
		if (oldBean.getBackEndId()<=0) {
			useport.remove(oldBean.getBackEndPort());
		}
		
		if (useport.contains(newBean.getListenPort())) {
			return viewBuilder.wrapError("变更的数据里监听端口号已经被其他服务配置数据使用", 20507);
		}
		Set<Integer> editport = new HashSet<>(3);
		editport.add(newBean.getListenPort());
		if (newBean.getFontEndId()<=0) {
			if (useport.contains(newBean.getFontEndPort())) {
				return viewBuilder.wrapError("变更的数据里前端端口号已经被其他服务配置数据使用", 20509);
			}
			if (!editport.add(newBean.getFontEndPort())) {
				return viewBuilder.wrapError("服务前端端口["+newBean.getFontEndPort()+"]重复使用", 20511);
			}
		}
		if (newBean.getBackEndId()<=0) {
			if (useport.contains(newBean.getBackEndPort())) {
				return viewBuilder.wrapError("变更的数据里后端端口号已经被其他服务配置数据使用", 20513);
			}
			if (!editport.add(newBean.getBackEndPort())) {
				return viewBuilder.wrapError("服务后端端口["+newBean.getBackEndPort()+"]重复使用", 20515);
			}
		}
		Set<Integer> assertexistid = new HashSet<>(3);
		if (!newBean.getListenId().equals(oldBean.getListenId())) {
			userset.getServiceList().getMap().get(oldBean.getListenId()).remove(newBean.getId());
			userset.getServiceList().getMap().get(newBean.getListenId()).add(newBean.getId());
			assertexistid.add(oldBean.getListenId());
		}
		if (!newBean.getFontEndId().equals(oldBean.getFontEndId())) {
			userset.getServiceList().getMap().get(oldBean.getFontEndId()).remove(newBean.getId());
			userset.getServiceList().getMap().get(newBean.getFontEndId()).add(newBean.getId());
			assertexistid.add(oldBean.getFontEndId());
		}
		if (!newBean.getBackEndId().equals(oldBean.getBackEndId())) {
			userset.getServiceList().getMap().get(oldBean.getBackEndId()).remove(newBean.getId());
			userset.getServiceList().getMap().get(newBean.getBackEndId()).add(newBean.getId());
			assertexistid.add(oldBean.getBackEndId());
		}
		if (isBs) {
			userset.getServiceList().getServiceBs().put(sid, newBean);
		} else {
			userset.getServiceList().getServiceCs().put(sid, newBean);
		}
		for (Integer e : assertexistid) {
			if (userset.getServiceList().getMap().get(e).isEmpty()) {
				userset.getServiceList().getMap().remove(e);
			}
		}
		userset.getComputerSelf().getPortSet().addAll(editport);
		return viewBuilder.wrap(true);
	}

	private ViewData addService(ServiceQuery query) {
		if (null == query.getsName()) {
			return viewBuilder.wrapError("服务名参数未指定", 30101);
		}
		if (!Util.isNonPositiveInteger(query.getsListenId())) {
			return viewBuilder.wrapError("服务监听参数非法", 30103);
		}
		if (!Util.isPort(query.getsListenPort())) {
			return viewBuilder.wrapError("服务监听端口非法", 30105);
		}
		if (!Util.isInteger(query.getFontEndId())) {
			return viewBuilder.wrapError("服务前端参数非法", 30107);
		}
		if (!Util.isPort(query.getFontEndPort())) {
			return viewBuilder.wrapError("服务前端端口非法", 30109);
		}
		if (!Util.isInteger(query.getBackEndId())) {
			return viewBuilder.wrapError("服务后端参数非法", 30111);
		}
		if (!Util.isPort(query.getBackEndPort())) {
			return viewBuilder.wrapError("服务后端端口非法", 30113);
		}

		int listenid = Integer.parseInt(query.getsListenId());
		int webid = Integer.parseInt(query.getFontEndId());
		int serviceid = Integer.parseInt(query.getBackEndId());
		int portListen = Integer.parseInt(query.getsListenPort());
		int portWeb = Integer.parseInt(query.getFontEndPort());
		int portService = Integer.parseInt(query.getBackEndPort());
		boolean isBs = query.isTypeBs();
		Set<Integer> newport = new HashSet<>(3);
		Set<Integer> useport = userset.getComputerSelf().getPortSet();
		if (useport.contains(portListen)) {
			return viewBuilder.wrapError("服务监听端口被占用", 30115);
		}
		newport.add(portListen);
		if (webid<=0) {
			if (useport.contains(portWeb)) {
				return viewBuilder.wrapError("服务前端端口被占用", 30117);
			}
			if (!newport.add(portWeb)) {
				return viewBuilder.wrapError("该信息里端口号["+portWeb+"]重复使用", 30119);
			}
		}
		if (serviceid<=0) {
			if (useport.contains(portService)) {
				return viewBuilder.wrapError("服务后端端口被占用", 30121);
			}
			if (!newport.add(portService)) {
				return viewBuilder.wrapError("该信息里端口号["+portService+"]重复使用", 30123);
			}
		}
		
		
		ServiceList serverList = userset.getServiceList();
		Integer mid = serverList.nextId();
		boolean existsId = true;
		for (int i = 0; i < 1000; i++) {
			if (serverList.getServiceBs().containsKey(mid)) {
				mid = serverList.nextId();
			} else if (serverList.getServiceCs().containsKey(mid)) {
				mid = serverList.nextId();
			} else {
				existsId = false;
				break;
			}
		}
		if (existsId) {
			return viewBuilder.wrapError("数据占用，请重新操作", 30125);
		}
		NginxService model = new NginxService();
		model.setId(mid);
		model.setServerName(query.getsName());
		model.setListenId(listenid);
		model.setListenPort(portListen);
		model.setFontEndId(webid);
		model.setFontEndPort(portWeb);
		model.setBackEndId(serviceid);
		model.setBackEndPort(portService);
		model.setSupportXLSX("true".equals(query.getsSendXlsx()));
		if (isBs) {
			serverList.getServiceBs().put(mid, model);
		} else {
			serverList.getServiceCs().put(mid, model);
		}
		userset.getComputerSelf().getPortSet().addAll(newport);
		if (null == userset.getServiceList().getMap().get(model.getListenId())) {
			userset.getServiceList().getMap().put(model.getListenId(), new HashSet<>());
		}
		if (null == userset.getServiceList().getMap().get(model.getFontEndId())) {
			userset.getServiceList().getMap().put(model.getFontEndId(), new HashSet<>());
		}
		if (null == userset.getServiceList().getMap().get(model.getBackEndId())) {
			userset.getServiceList().getMap().put(model.getBackEndId(), new HashSet<>());
		}
		userset.getServiceList().getMap().get(model.getListenId()).add(mid);
		userset.getServiceList().getMap().get(model.getFontEndId()).add(mid);
		userset.getServiceList().getMap().get(model.getBackEndId()).add(mid);
		return viewBuilder.wrap(true);
	}

	@Override
	public ViewData getLocalIp() {
		return commonIpSelfInterface.getLocalIpList();
	}

	@Override
	public ViewData getAllIp() {
		return commonIpAllInterface.getAllIpList();
	}

	@Override
	public ViewData previewjson() {
		return viewBuilder.wrapToJson(userset);
	}
	
	
	private boolean merge(NginxService newBean, NginxService oldBean) {
		newBean.setId(oldBean.getId());
		boolean issame = true;
		if (null!= newBean.getServerName() && newBean.getServerName().length()>0) {
			if (!newBean.getServerName().equals(oldBean.getServerName())) {
				issame = false;
			}
		} else {
			newBean.setServerName(oldBean.getServerName());
		}
		if (null != newBean.getListenId()) {
			if (!newBean.getListenId().equals(oldBean.getListenId())) {
				issame = false;
			}
		} else {
			newBean.setListenId(oldBean.getListenId());
		}
		if (null != newBean.getListenPort()) {
			if (!newBean.getListenPort().equals(oldBean.getListenPort())) {
				issame = false;
			}
		} else {
			newBean.setListenPort(oldBean.getListenPort());
		}
		if (null != newBean.getFontEndId()) {
			if (!newBean.getFontEndId().equals(oldBean.getFontEndId())) {
				issame = false;
			}
		} else {
			newBean.setFontEndId(oldBean.getFontEndId());
		}
		if (null != newBean.getFontEndPort()) {
			if (!newBean.getFontEndPort().equals(oldBean.getFontEndPort())) {
				issame = false;
			}
		} else {
			newBean.setFontEndPort(oldBean.getFontEndPort());
		}
		if (null != newBean.getBackEndId()) {
			if (!newBean.getBackEndId().equals(oldBean.getBackEndId())) {
				issame = false;
			}
		} else {
			newBean.setBackEndId(oldBean.getBackEndId());
		}
		if (null != newBean.getBackEndPort()) {
			if (!newBean.getBackEndPort().equals(oldBean.getBackEndPort())) {
				issame = false;
			}
		} else {
			newBean.setBackEndPort(oldBean.getBackEndPort());
		}
		if (null != newBean.getSupportXLSX()) {
			if (!newBean.getSupportXLSX().equals(oldBean.getSupportXLSX())) {
				issame = false;
			}
		} else {
			newBean.setSupportXLSX(oldBean.getSupportXLSX());
		}
		return issame;
	}
}
